/*
Copyright [2020] [https://www.xiaonuo.vip]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：

1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Snowy源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处，作者声明等。
4.分发源码时候，请注明软件出处 https://gitee.com/xiaonuobase/snowy
5.在修改包名，模块名称，项目代码等时，请注明软件出处 https://gitee.com/xiaonuobase/snowy
6.若您的项目无法满足以上几点，可申请商业授权，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.modular.aiboxalertnoticesetting.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.facedoor.modular.memberuser.entity.MemberUser;
import vip.xiaonuo.facedoor.modular.memberuser.service.MemberUserService;
import vip.xiaonuo.megvii.captures.model.base.define.AlertorTypeDefine;
import vip.xiaonuo.megvii.captures.model.base.define.Option;
import vip.xiaonuo.modular.aiboxalertnoticesetting.entity.AiBoxAlertNoticeSetting;
import vip.xiaonuo.modular.aiboxalertnoticesetting.enums.AiBoxAlertNoticeSettingExceptionEnum;
import vip.xiaonuo.modular.aiboxalertnoticesetting.mapper.AiBoxAlertNoticeSettingMapper;
import vip.xiaonuo.modular.aiboxalertnoticesetting.param.AiBoxAlertNoticeSettingParam;
import vip.xiaonuo.modular.aiboxalertnoticesetting.param.AiBoxAlertNoticeSettingSave;
import vip.xiaonuo.modular.aiboxalertnoticesetting.param.User;
import vip.xiaonuo.modular.aiboxalertnoticesetting.service.AiBoxAlertNoticeSettingService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.modular.aiboxalertnoticesetting.vo.MemberInfo;
import vip.xiaonuo.modular.aiboxalertnoticesetting.vo.NoticeSettingVO;
import vip.xiaonuo.modular.aiboxalertnoticesetting.vo.SettingDetail;
import vip.xiaonuo.modular.devicemegvii.entity.DeviceMegvii;
import vip.xiaonuo.modular.devicemegvii.service.DeviceMegviiService;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * 智能分析盒预警提醒设置service接口实现类
 *
 * @author JOE
 * @date 2022-11-03 10:40:07
 */
@Service
public class AiBoxAlertNoticeSettingServiceImpl extends ServiceImpl<AiBoxAlertNoticeSettingMapper, AiBoxAlertNoticeSetting> implements AiBoxAlertNoticeSettingService {

    @Resource
    private DeviceMegviiService service;

    @Resource
    private MemberUserService userService;

    @Override
    public PageResult<AiBoxAlertNoticeSetting> page(AiBoxAlertNoticeSettingParam aiBoxAlertNoticeSettingParam) {
        QueryWrapper<AiBoxAlertNoticeSetting> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(aiBoxAlertNoticeSettingParam)) {

            // 根据设备外键 查询
            if (ObjectUtil.isNotEmpty(aiBoxAlertNoticeSettingParam.getDeviceId())) {
                queryWrapper.lambda().eq(AiBoxAlertNoticeSetting::getDeviceId, aiBoxAlertNoticeSettingParam.getDeviceId());
            }
            // 根据预警类型 查询
            if (ObjectUtil.isNotEmpty(aiBoxAlertNoticeSettingParam.getWarningType())) {
                queryWrapper.lambda().eq(AiBoxAlertNoticeSetting::getWarningType, aiBoxAlertNoticeSettingParam.getWarningType());
            }
        }
        return new PageResult<>(this.page(PageFactory.defaultPage(), queryWrapper));
    }

    @Override
    public List<AiBoxAlertNoticeSetting> list(AiBoxAlertNoticeSettingParam aiBoxAlertNoticeSettingParam) {
        return this.list();
    }

    @Override
    public void add(AiBoxAlertNoticeSettingParam aiBoxAlertNoticeSettingParam) {
        AiBoxAlertNoticeSetting aiBoxAlertNoticeSetting = new AiBoxAlertNoticeSetting();
        BeanUtil.copyProperties(aiBoxAlertNoticeSettingParam, aiBoxAlertNoticeSetting);
        this.save(aiBoxAlertNoticeSetting);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(AiBoxAlertNoticeSettingParam aiBoxAlertNoticeSettingParam) {
        this.removeById(aiBoxAlertNoticeSettingParam.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(AiBoxAlertNoticeSettingParam aiBoxAlertNoticeSettingParam) {
        AiBoxAlertNoticeSetting aiBoxAlertNoticeSetting = this.queryAiBoxAlertNoticeSetting(aiBoxAlertNoticeSettingParam);
        BeanUtil.copyProperties(aiBoxAlertNoticeSettingParam, aiBoxAlertNoticeSetting);
        this.updateById(aiBoxAlertNoticeSetting);
    }

    @Override
    public AiBoxAlertNoticeSetting detail(AiBoxAlertNoticeSettingParam aiBoxAlertNoticeSettingParam) {
        return this.queryAiBoxAlertNoticeSetting(aiBoxAlertNoticeSettingParam);
    }



    /**
     * 获取智能分析盒预警提醒设置
     *
     * @author JOE
     * @date 2022-11-03 10:40:07
     */
    private AiBoxAlertNoticeSetting queryAiBoxAlertNoticeSetting(AiBoxAlertNoticeSettingParam aiBoxAlertNoticeSettingParam) {
        AiBoxAlertNoticeSetting aiBoxAlertNoticeSetting = this.getById(aiBoxAlertNoticeSettingParam.getId());
        if (ObjectUtil.isNull(aiBoxAlertNoticeSetting)) {
            throw new ServiceException(AiBoxAlertNoticeSettingExceptionEnum.NOT_EXIST);
        }
        return aiBoxAlertNoticeSetting;
    }

    @Override
    public List<NoticeSettingVO> listSetting() {
        List<DeviceMegvii> devices = service.list(); // columns

        List<Option> alertTypes = AlertorTypeDefine.getOptions();
        List<NoticeSettingVO> settings = new LinkedList<>();
        for(Option option : alertTypes){
            NoticeSettingVO vo = new NoticeSettingVO();
            vo.setAlertType(option.getName());
            vo.setAlertName(option.getCode());

            List<SettingDetail> details = new LinkedList<>();
            for(DeviceMegvii device : devices){
                SettingDetail detail = new SettingDetail();
                detail.setDeviceCode(device.getSnCode());
                detail.setDeviceId(device.getId());
                detail.setAlertType(option.getCode());
                // 获取设置的通知人员
                List<AiBoxAlertNoticeSetting> existSettings = this.list(new LambdaQueryWrapper<AiBoxAlertNoticeSetting>()
                        .eq(AiBoxAlertNoticeSetting :: getDeviceId, device.getId())
                        .eq(AiBoxAlertNoticeSetting :: getWarningType , option.getCode()));

                List<MemberInfo> members = new LinkedList<>();
                for(AiBoxAlertNoticeSetting setting : existSettings){
                    MemberUser user = userService.getById(setting.getMemberUserId());
                    if(user == null ){
                        this.removeById(setting.getId());
                        continue;
                    }
                    members.add(new MemberInfo(setting.getId(),user.getName()));
                }
                detail.setUserList(members);
                details.add(detail);
            }
            vo.setDetails(details);
            settings.add(vo);
        }
        return settings;
    }

    @Override
    public void set(AiBoxAlertNoticeSettingSave saveBean) {
        int saveMode = saveBean.getSaveMode();
        int setMode = saveBean.getSetMode();

        long deviceId = saveBean.getDeviceId();
        String warningType = saveBean.getAlertType();



        List<DeviceMegvii> devices = service.list();
        List<Option> alertOptions = AlertorTypeDefine.getOptions();

        if(saveMode == 2){ // 覆盖保存, 先清除当前设置
            // 清除当前设置
            if(setMode == 1){ // 仅清除当前单元格的设置
                this.remove(new LambdaQueryWrapper<AiBoxAlertNoticeSetting>()
                        .eq(AiBoxAlertNoticeSetting :: getDeviceId, deviceId)
                        .eq(AiBoxAlertNoticeSetting :: getWarningType , warningType));

            }else if(setMode == 2){ // 清除当前预警类型的设置
                this.remove(new LambdaQueryWrapper<AiBoxAlertNoticeSetting>()
                        .eq(AiBoxAlertNoticeSetting :: getWarningType , warningType));

            }else if(setMode == 3){// 清除当前设备的设置
                this.remove(new LambdaQueryWrapper<AiBoxAlertNoticeSetting>()
                        .eq(AiBoxAlertNoticeSetting :: getDeviceId, deviceId));
            }else if(setMode == 4){// 清除所有的设置
                this.remove(new LambdaQueryWrapper<AiBoxAlertNoticeSetting>());
            }
        }
        List<User> users = saveBean.getUsers();

        List<AiBoxAlertNoticeSetting> toSave = new ArrayList<>();
        if(setMode == 1){ // 当前单元格的设置
            for(User user : users){
                saveOrBreakSetting(toSave,warningType,deviceId,user.getUserId());
            }
        }else if(setMode == 2){ // 预警类型的设置
            for(DeviceMegvii device : devices){
                for(User user : users){
                    saveOrBreakSetting(toSave,warningType,device.getId(),user.getUserId());
                }
            }
        }else if(setMode == 3){// 当前设备的设置
            for(Option option : alertOptions){
                for(User user : users){
                    saveOrBreakSetting(toSave,option.getCode(),deviceId,user.getUserId());
                }
            }
        }else if(setMode == 4){// 所有设置
            for(DeviceMegvii device : devices){
                for(Option option : alertOptions){
                    for(User user : users){
                        saveOrBreakSetting(toSave,option.getCode(),device.getId(),user.getUserId());
                    }
                }
            }
        }
        this.saveBatch(toSave);
    }

    private void saveOrBreakSetting(List<AiBoxAlertNoticeSetting> toSave, String warningType, Long deviceId, Long userId){
        AiBoxAlertNoticeSetting setting = this.getOne(new LambdaQueryWrapper<AiBoxAlertNoticeSetting>()
                .eq(AiBoxAlertNoticeSetting :: getDeviceId, deviceId)
                .eq(AiBoxAlertNoticeSetting :: getWarningType , warningType)
                .eq(AiBoxAlertNoticeSetting::getMemberUserId , userId));
        if(setting == null){
            setting = new AiBoxAlertNoticeSetting();
            setting.setDeviceId(deviceId);
            setting.setWarningType(warningType);
            setting.setMemberUserId(userId);
            toSave.add(setting);
        }
    }


}
